package com.woniuxy.exam.service.impl;

import com.itextpdf.text.Document;
import com.itextpdf.text.DocumentException;
import com.woniuxy.commons.entity.*;
import com.woniuxy.exam.entity.PaperDto;
import com.woniuxy.exam.entity.QuestionsOfPaperDto;
import com.woniuxy.exam.mapper.PaperMapper;
import com.woniuxy.exam.service.*;
import com.woniuxy.exam.utils.PaperUtil;
import com.woniuxy.exam.utils.PrintUtil;
import lombok.Data;
import org.ehcache.config.ResourceUnit;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.ResourceUtils;

import java.io.FileNotFoundException;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

/**
 * @Author 余枭春
 * @Date 2020/7/16 19:06
 * @Description
 **/
@Service
@Data
public class PaperServiceImpl implements PaperService {
    public static final int TESTTYPE_TEST = 1;
    public static final int TESTTYPE_EXAM = 2;
    public static final int TESTTYPE_MANUAL = 1;
    public static final int TESTTYPE_AUTO = 2;
    public static final int TIME_DEFULT = 120;
    public static final int STATUS_NOT = 1;
    public static final int STATUS_PUBLISH = 2;
    //试卷mapper
    @Autowired
    private PaperMapper paperMaper;
    //试卷结构
    @Autowired
    private PaperStructureService paperStructureService;
    @Autowired
    private SingleChoiceService singleChoiceService;
    @Autowired
    private MultipleChoiceService multipleChoiceService;
    @Autowired
    private TrueOrFalseService trueOrFalseService;
    @Autowired
    private BlankFillingService blankFillingService;
    @Autowired
    private ShortAnswerService shortAnswerService;

    @Override
    public List<Paper> allPaper() {
        return paperMaper.allTestPaper();
    }

    @Override
    public List<Paper> allPaperWithConditions(Paper paper) {
        return paperMaper.listPapersWithCondition(paper);
    }


    @Override
    public Paper findPaper(int paperId) {
        return paperMaper.findTestPaperById(paperId);
    }

    @Override
    public int createPaper(Paper paper) {
        if (paper.getTime() == 0) {
            paper.setTime(TIME_DEFULT);
        }
        int res = paperMaper.createPaper(paper);
        if (res > 0) {
            Paper paperNew = findPaperByName(paper.getName());
            return paperNew.getId();
        }
        return 0;
    }

    @Override
    public int updatePaper(Paper paper) {
        int res = paperMaper.updatePaper(paper);
        if (res > 0) {
            return res;
        } else {
            return 0;
        }
    }

    @Override
    public int updatePaperStatus(Integer status, Integer paperId) {
        Paper paper = paperMaper.findTestPaperById(paperId);
        if (paper == null) {
            //TODO 设置状态码
            return -1;
        }
        if (status == 1) {
            paper.setStatus(STATUS_NOT);
        }
        if (status == 2) {
            paper.setStatus(STATUS_PUBLISH);
        } else {
            return -1;
        }
        int res = paperMaper.updatePaperStatus(paper);
        return res;
    }

    @Override
    public Paper findPaperByName(String name) {
        return paperMaper.findTestPaperByName(name);
    }

    /**
     * 完善一个试卷，通过题库id，在题库中自动中体自动组卷
     *
     * @param paperDto
     * @return -3代表方法内出错，-2代表数据库插入失败，-1代表没有题库，1代表成功插入
     */
    @Override
    public int completePaperAuto(PaperDto paperDto) {
        //先判断是否有题库类型
        if (paperDto.getQuestionBankId() == 0) {
            return -1;
        }
        //新生成一个试卷结构
        PaperStructure paperStructure = paperStructureService.findPaperStructureByPaperId(paperDto.getId());
        if (paperStructure == null) {
            PaperStructure paperStructure1=new PaperStructure();
            paperStructure1.setPaperId(paperDto.getId());
            paperStructureService.insertPaperStructure(paperStructure1);
            paperStructure = paperStructureService.findPaperStructureByPaperId(paperDto.getId());
        }else {
            //如果不是，就把试卷的题删了
            paperMaper.deleteQuestionsOfPaperByPaperId(paperDto.getId());
        }
        //通过题库id查询题库
        //循环判断每个题型的数目
        //定义一个题目业务类
        QuestionsOfPaperDto quesetions = new QuestionsOfPaperDto();
        quesetions.setPaperId(paperDto.getId());
        //题号
        int num = 1;
        //定义一个存放已经放进去对应题型id的数组
        List<Integer> ids = new ArrayList<>();//存放已经加载的id
        //单选题数组
        List<Integer> questionIds = singleChoiceService.selectIdByBankId(paperDto.getQuestionBankId());
        //存放同题型的数目
        int flag = paperStructure.getSingleChoiceNum();//单选题
        while (flag > 0) {
            int id = (int) ((Math.random() * questionIds.size()) + 1);
            if (ids.contains(id)) {
                continue;
            }
            quesetions.setQuestionNum(num);
            quesetions.setSingleChoiceId(id);
            ids.add(id);
            int res = paperMaper.completePaper(quesetions);
            if (res > 0) {
                num++;
                flag--;
            } else {
                return -2;
            }
        }
        //清空id数组
        ids.clear();
        //清空question
        quesetions.setSingleChoiceId(0);
        flag = paperStructure.getMultipleChoiceNum();//多选题
        questionIds = multipleChoiceService.selectIdByBankId(paperDto.getQuestionBankId());
        while (flag > 0) {
            int id = (int) ((Math.random() * questionIds.size()) + 1);
            if (ids.contains(id)) {
                continue;
            }
            quesetions.setQuestionNum(num);
            quesetions.setMultipleChoiceId(id);
            ids.add(id);
            int res = paperMaper.completePaper(quesetions);
            if (res > 0) {
                num++;
                flag--;
            } else {
                return -2;
            }
        }
        ids.clear();
        quesetions.setMultipleChoiceId(0);
        flag = paperStructure.getTrueOrFalseNum();//判断题
        questionIds = trueOrFalseService.selectIdByBankId(paperDto.getQuestionBankId());
        while (flag > 0) {
            int id = (int) ((Math.random() * questionIds.size()) + 1);
            if (ids.contains(id)) {
                continue;
            }
            quesetions.setQuestionNum(num);
            quesetions.setTrueOrFalseId(id);
            ids.add(id);
            int res = paperMaper.completePaper(quesetions);
            if (res > 0) {
                num++;
                flag--;
            } else {
                return -2;
            }
        }
        ids.clear();
        quesetions.setTrueOrFalseId(0);
        flag = paperStructure.getCompletionNum();//填空题
        questionIds = blankFillingService.selectIdByBankId(paperDto.getQuestionBankId());
        while (flag > 0) {
            int id = (int) ((Math.random() * questionIds.size()) + 1);
            if (ids.contains(id)) {
                continue;
            }
            quesetions.setQuestionNum(num);
            quesetions.setBlankFillingId(id);
            ids.add(id);
            int res = paperMaper.completePaper(quesetions);
            if (res > 0) {
                num++;
                flag--;
            } else {
                return -2;
            }
        }
        ids.clear();
        quesetions.setBlankFillingId(0);
        flag = paperStructure.getAnswerNum();//简答题
        questionIds = shortAnswerService.selectIdByBankId(paperDto.getQuestionBankId());
        while (flag > 0) {
            int id = (int) ((Math.random() * questionIds.size()) + 1);
            if (ids.contains(id)) {
                continue;
            }
            quesetions.setQuestionNum(num);
            quesetions.setShortAnswerId(id);
            ids.add(id);
            int res = paperMaper.completePaper(quesetions);
            if (res > 0) {
                num++;
                flag--;
            } else {
                return -2;
            }
        }
        if (paperStructure.getQuestionTotalNum() == num - 1) {
            return 1;
        }
        return -3;
    }

    /**
     * 手动组卷
     *
     * @param paperDto
     * @return 3:自动组卷，-2：插入失败
     */
    @Override
    public int completePaper(PaperDto paperDto) {
        if (paperDto.getPaperStructure() == null) {
            //将试卷结构添加进来
            PaperStructure paperStructure = paperStructureService.findPaperStructureByPaperId(paperDto.getId());
            if (paperStructure == null) {
                if (completePaperAuto(paperDto) > 0) {
                    //试卷自动组卷
                    return 3;
                }
            }
            paperDto.setPaperStructure(paperStructure);
        }
        //将前端中所有的题封存进试卷
        for (int i = 0; i < paperDto.getPaperStructure().getQuestionTotalNum(); i++) {
            int res = paperMaper.completePaper(paperDto.getQuestions().get(i));
            if (res <= 0) {
                return -2;
            }
        }
        //插入成功
        return 1;
    }

    /**
     * 获取完整试卷
     *
     * @param paperId
     * @return -1:没有该试卷
     */
    @Override
    public PaperDto getFullPaper(int paperId) {
        //试卷基本信息
        Paper paper = paperMaper.findTestPaperById(paperId);
        if (paper == null) {
            System.out.println("=============================3");
            //TODO 抛自定义异常
            return null;
        }
        //试卷结构
        PaperStructure paperStructure = paperStructureService.findPaperStructureByPaperId(paperId);
        if (paperStructure == null) {
            System.out.println("=============================2");
            //TODO 抛自定义异常
            return null;
        }
        //声明一个试卷封装类
        PaperDto paperDto = new PaperDto();
        //将试卷封装
        PaperUtil.paperToPaperDto(paper, paperDto);
        paperDto.setPaperStructure(paperStructure);
        //将试卷题号和题的id封存
        List<QuestionsOfPaperDto> questionsOfPaperDtos = paperMaper.getQuestionsOfPaperDtosByPaperId(paperId);
        if (questionsOfPaperDtos == null) {
            System.out.println("=============================1");
            //TODO 抛自定义异常
            return null;
        }
        paperDto.setQuestions(questionsOfPaperDtos);
        //试卷题号
        int num = 1;
        //试卷查询类
        QuestionsOfPaperDto question = new QuestionsOfPaperDto();
        question.setPaperId(paperId);
/*
        for (int i = 0; i <paperStructure.getQuestionTotalNum() ; i++) {
            //根据题号组卷
            question
        }

  */
        //-----------------------------------------------//
        //查询试卷试题表
        //TODO 自定义异常类，当mapper查询出错的时候弹出
        if (paperStructure.getSingleChoiceNum() > 0) {
            List<SingleChoice> singleChoices = new ArrayList<>();
            for (int i = 0; i < paperStructure.getSingleChoiceNum(); i++) {
                question.setQuestionNum(num);
                question = paperMaper.getQuestionByPaperIdAndNum(question);
                singleChoices.add(singleChoiceService.selectByPrimaryKey(question.getSingleChoiceId()));
                num++;
            }
            paperDto.setSingleChoices(singleChoices);
        }
        if (paperStructure.getMultipleChoiceNum() > 0) {
            List<MultipleChoice> multipleChoices = new ArrayList<>();
            for (int i = 0; i < paperStructure.getMultipleChoiceNum(); i++) {
                question.setQuestionNum(num);
                question = paperMaper.getQuestionByPaperIdAndNum(question);
                multipleChoices.add(multipleChoiceService.selectByPrimaryKey(question.getMultipleChoiceId()));
                num++;
            }
            paperDto.setMultipleChoices(multipleChoices);
        }
        if (paperStructure.getTrueOrFalseNum() > 0) {
            List<TrueOrFalse> trueOrFalses = new ArrayList<>();
            for (int i = 0; i < paperStructure.getTrueOrFalseNum(); i++) {
                question.setQuestionNum(num);
                question = paperMaper.getQuestionByPaperIdAndNum(question);
                trueOrFalses.add(trueOrFalseService.selectByPrimaryKey(question.getTrueOrFalseId()));
                num++;
            }
            paperDto.setTrueOrFalses(trueOrFalses);
        }
        if (paperStructure.getCompletionNum() > 0) {
            List<BlankFilling> blankFillings = new ArrayList<>();
            for (int i = 0; i < paperStructure.getCompletionNum(); i++) {
                question.setQuestionNum(num);
                question = paperMaper.getQuestionByPaperIdAndNum(question);
                blankFillings.add(blankFillingService.selectByPrimaryKey(question.getBlankFillingId()));
                num++;
            }
            paperDto.setBlankFillings(blankFillings);
        }
        if (paperStructure.getAnswerNum() > 0) {
            List<ShortAnswer> shortAnswers = new ArrayList<>();
            for (int i = 0; i < paperStructure.getAnswerNum(); i++) {
                question.setQuestionNum(num);
                question = paperMaper.getQuestionByPaperIdAndNum(question);
                shortAnswers.add(shortAnswerService.selectByPrimaryKey(question.getShortAnswerId()));
                num++;
            }
            paperDto.setShortAnswers(shortAnswers);
        }
        if (num - 1 == paperStructure.getQuestionTotalNum()) {
            return paperDto;
        }
        //TODO 抛自定义异常，程序出错
        System.out.println("caonima");
        return paperDto;
        //return null;
    }

    private static  String DEST;

    static {
        try {
            DEST = ResourceUtils.getURL("classpath:").getPath();
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        }
    }

    /**
     * 打印试卷
     *
     * @param paperId
     * @return
     */
    @Override
    public String printPaper(int paperId) throws IOException, DocumentException {
        try {
            PaperDto paperDto = getFullPaper(paperId);
            String path = DEST + paperDto.getName() + ".pdf";
            //调用工具类直接生成试卷PDF，并保存到特定位置，返回地址字符串
            //TODO 书写进试卷serviceimpl中
            System.out.println("--------------");
            Document document = PrintUtil.createPdf(path, paperDto);
            PrintUtil.createFile(document, paperDto);
            document.close();
            System.out.println("==------------");
            return path;
        } catch (IOException | DocumentException e1) {
            //TODO 自定义异常code
            e1.printStackTrace();
            return null;
        } catch (Exception e) {
            //TODO 自定义异常code
            e.printStackTrace();
            return null;
        }
    }
}
